﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonLib;
using System.Data;

namespace Constructor
{
    public class Domain : IDomain
    {
        private int _min;
        private int _max;
        public Domain(string id)
        {
            ID = id;
            System.Data.DataRow[] values = External.ds.Tables["domens_params"].Select("Название_домена = '" + ID + "'");
            if (values.Length > 0) CheckValue(values[0]["Значения домена"].ToString());
        }
        public string ID { get; set; }
        public DomainType Type
        {
            get
            {
                if (ID == "Images")
                    return DomainType.Image;
                System.Data.DataRow[] values = External.ds.Tables["domens_params"].Select("Название_домена = '" + ID + "'");
                if (values.Count() > 1) return DomainType.Enum;
                if (values.Count() == 1 && CheckValue(values[0]["Значения домена"].ToString()))
                    return DomainType.Number;
                return CommonLib.DomainType.Enum;
            }
            set { }
        }
        public int MinValue { get { return _min; } set { } }
        public int MaxValue { get { return _max; } set { } }

        public int GetValueInRange(double value)
        { return GetValueInRange((int)value); }

        public int GetValueInRange(int value)
        { return value < MinValue ? MinValue : Math.Min(value, MaxValue); }

        public List<string> Values
        {
            get
            {
                List<string> result = new List<string>(); ;
                //if (Type == DomainType.Enum)
                {
                    System.Data.DataRow[] values = External.ds.Tables["domens_params"].Select("Название_домена = '" + ID + "'");
                    foreach (DataRow value in values)
                        result.Add(value["Значения домена"].ToString());
                }
                return result;
            }
            set { }
        }

        private bool CheckValue(string value)
        {
            if (value.Contains(".."))
            {
                string[] splitResult = value.Split(new string[] { ".." }, 2, StringSplitOptions.None);
                if (splitResult.Length == 2)
                {
                    if (int.TryParse(splitResult[0], out _min) && int.TryParse(splitResult[1], out _max)
                        && MinValue < MaxValue)
                        return true;
                }
            }
            return false;
        }

        public static bool Exists(string name)
        {
            System.Data.DataRow[] values = External.ds.Tables["domens_params"].Select("Название_домена = '" + name + "'");
            return values.Count() > 0;
        }

        /// <summary>
        /// Содержание значения в домене.
        /// </summary>
        public bool Contains(string value)
        {
            switch (Type)
            {
                case DomainType.Image:
                    return External.images.LoadedImages.ContainsKey(value);
                case DomainType.Enum:
                    return Values.Contains(value);
                case DomainType.Number:
                    int int_val;
                    if (int.TryParse(value, out int_val))
                        return int_val <= MaxValue && int_val >= MinValue;
                    break;
            }
            return false;
        }

        /// <summary>
        /// Содержание значения в домене с учетом ограничений.
        /// </summary>
        public bool Contains(string value, string constraints)
        {
            switch (Type)
            {
                case DomainType.Image:
                    return External.images.LoadedImages.ContainsKey(value);
                case DomainType.Enum:
                    return Values.Contains(value) && constraints.Split(',').Contains(value);
                case DomainType.Number:
                    {
                        MinMax mx = new MinMax(constraints);
                        int int_val = 0;
                        return mx.valid && int.TryParse(value, out int_val)
                        && mx.Min >= MinValue && mx.Max <= MaxValue
                            && int_val >= mx.Min && int_val <= mx.Max;
                    }
            }
            return false;
        }
    }
}
